package cn.pconline.autoclub.service;

import cn.pconline.autoclub.entity.Club;
import cn.pconline.autoclub.entity.Promotion;
import cn.pconline.autoclub.entity.PromotionPublish;
import cn.pconline.autoclub.entity.Theme;
import cn.pconline.autoclub.util.DateUtils;
import cn.pconline.autoclub.util.EncodeUtils;
import cn.pconline.autoclub.util.Pager;
import cn.pconline.autoclub.util.StringUtil;

import com.alibaba.fastjson.JSONObject;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import org.gelivable.dao.GeliDao;
import org.gelivable.dao.GeliOrm;
import org.gelivable.dao.SqlBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;

/**
 * @author fengguosen 创建时间：2014-10-16 优惠活动Service
 */
public class PromotionService {

    private static final Logger log = LoggerFactory.getLogger(PromotionService.class);
    @Autowired
    GeliDao geliDao;
    @Autowired
    GeliOrm geliOrm;
    @Autowired
    private PagerService pagerService;
    @Autowired
    private ClubService clubService;

    /**
     *
     * @Description: 查找单个Promotion
     * @param:
     * @param id
     * @return: Promotion
     */
    public Promotion findPromotion(long id) {
        try {
            return geliDao.find(Promotion.class, id);
        } catch (EmptyResultDataAccessException e) {
            return null;
        }
    }

    /**
     * @Description: 查找单个PromotionPublish
     * @param:
     * @param id
     * @return: PromotionPublish
     */
    public PromotionPublish findPromotionPublish(long id) {
        try {
            return geliDao.find(PromotionPublish.class, id);
        } catch (EmptyResultDataAccessException e) {
            return null;
        }
    }

    /**
     * @Description: 更新promotion
     * @param:
     * @param promotion
     * @param:
     * @return int
     */
    public int updatePromotion(Promotion promotion) {
        return geliDao.update(promotion);
    }

    /**
     * @Description: 列举所有的优惠活动(内置排序)
     * @param: int pageNo, int pageSize
     * @param:
     * @return Pager<Promotion>
     */
    public Pager<Promotion> pagePromotion(int pageNo, int pageSize) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql("select promotion_id from ").appendSql(geliOrm.getTableName(Promotion.class)).appendSql(" where status>=0");
        sql.appendSql(" order by sort_weight desc");
        return pagerService.pager(Promotion.class, sql, pageNo, pageSize);
    }

    /**
     * @Description: 列举所有的车友会优惠活动
     * @param: int pageNo, int pageSize
     * @param:
     * @return Pager<Promotion>
     */
    public Pager<PromotionPublish> pagePromotionPublish(long provinceId, long cityId, long brandId, long serialId, long themeId, long clubId, int pageNo, int pageSize) {
        SqlBuilder sql = new SqlBuilder();
        String nowDate = DateUtils.format(new Date());
        sql.appendSql("select publish_id from ").appendSql(geliOrm.getTableName(PromotionPublish.class)).appendSql(" publish, ");
        sql.appendSql(geliOrm.getTableName(Promotion.class)).appendSql( " promotion ");
        sql.appendSql(" where 1 = 1 ");
        sql.appendSql(" and publish.promotion_id = promotion.promotion_id " );
        sql.appendSql(" and promotion.status = ").appendValue(Promotion.STATUS_NORMAL);
        sql.appendSql(" and publish.city_id = ").appendValue(cityId);// cityId是可以为0的情况
        if (provinceId > 0) {
            sql.appendSql(" and publish.province_id = ").appendValue(provinceId);
        }
        if (brandId > 0) {
            sql.appendSql(" and publish.brand_id = ").appendValue(brandId);
        }
        if (serialId > 0) {
            sql.appendSql(" and publish.serial_id = ").appendValue(serialId);
        }
        if (themeId > 0) {
            sql.appendSql(" and publish.theme_id = ").appendValue(themeId);
        }
        if (clubId > 0) {
            sql.appendSql(" and publish.club_id = ").appendValue(clubId);
        }
        sql.appendSql(" and publish.start_date <= ").appendValue(nowDate);
        sql.appendSql(" and publish.end_date >= ").appendValue(nowDate);
        sql.appendSql(" order by publish.create_at desc");
        return pagerService.pager(PromotionPublish.class, sql, pageNo, pageSize);
    }

    /**
     * 获取同城优惠活动(分页）
     *
     * @param provinceId
     * @param cityId
     * @param pageNo
     * @param pageSize
     * @return
     */
    public Pager<PromotionPublish> pagePromotionPublish(long provinceId, long cityId, int pageNo, int pageSize) {
        SqlBuilder sql = new SqlBuilder();
        String nowDate = DateUtils.format(new Date());
        sql.appendSql("select publish_id from ").appendSql(geliOrm.getTableName(PromotionPublish.class)).appendSql(" publish, ");
        sql.appendSql(geliOrm.getTableName(Promotion.class)).appendSql( " promotion ");
        sql.appendSql(" where 1 = 1 ");
        sql.appendSql(" and publish.promotion_id = promotion.promotion_id " );
        sql.appendSql(" and promotion.status = ").appendValue(Promotion.STATUS_NORMAL);
        sql.appendSql(" and publish.city_id = ").appendValue(cityId);// cityId是可以为0的情况
        if (provinceId > 0) {
            sql.appendSql(" and publish.province_id = ").appendValue(provinceId);
        }
        sql.appendSql(" and publish.start_date <= ").appendValue(nowDate);
        sql.appendSql(" and publish.end_date >= ").appendValue(nowDate);
        sql.appendSql(" GROUP BY publish.promotion_id,publish.province_id,publish.city_id ");
        sql.appendSql(" order by publish.create_at desc");
        
        Pager<PromotionPublish> pager = new Pager<PromotionPublish>();
        pager.setPageNo(pageNo);
        pager.setPageSize(pageSize);
        if (pageNo < 0 || pageNo > pager.getPageCount() || isPageOutRange(pageNo, pageSize)) {
            throw new Pager.IllegalPageException("非法页码: " + pageNo);
        }
        try {
            pager.setResultList(geliDao.page(PromotionPublish.class, sql.getSql(), pageNo, pageSize, sql.getValues()));
            String countSql = sql.getSql().replace(sql.getSql().substring(0, sql.getSql().toLowerCase().indexOf("from")), "select count(distinct publish.promotion_id,publish.province_id,publish.city_id) ");
            countSql = countSql.replace(countSql.substring(countSql.toLowerCase().indexOf("group by"), countSql.length()), "");
            int count = geliDao.count(countSql, sql.getValues());
            pager.setTotal(count);
        } catch (EmptyResultDataAccessException e) {
            log.warn("empty result!sql:{} values:{},pageNo:{},pageSize:{}",
                    sql.getSql(), StringUtil.toString(sql.getValues()),pageNo,pageSize);
        }
        return pager;
    }
    
    private boolean isPageOutRange(int pageNo, int pageSize) {
        int offset = (pageNo - 1) * pageSize;
        if (offset < 0 || offset > Integer.MAX_VALUE) {
            return true;
        }
        return false;
    }
    /**
     * @Description: 根据条件获取车友会优惠活动
     * @param:
     * @param provinceId 省份id（小于等于0不作为条件）
     * @param:
     * @param cityId	城市id（小于等于0不作为条件）
     * @param:
     * @param limit	返回多少条记录
     * @param:
     * @return 所有符合条件的PromotionPublish
     * @return: List<PromotionPublish>
     * @Date 2014-10-16 下午05:01:06
     */
    public List<PromotionPublish> listPromotionPublishByCondition(long provinceId, long cityId, int limit) {
        String nowDate = DateUtils.format(new Date());
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql("select publish_id from ").appendSql(geliOrm.getTableName(PromotionPublish.class)).appendSql(" publish, ");
        sql.appendSql(geliOrm.getTableName(Promotion.class)).appendSql( " promotion ");
        sql.appendSql(" where 1 = 1 ");
        sql.appendSql(" and publish.promotion_id = promotion.promotion_id " );
        sql.appendSql(" and promotion.status = ").appendValue(Promotion.STATUS_NORMAL);
        sql.appendSql(" and publish.city_id = ").appendValue(cityId);//cityId是可以为0的情况
        if (provinceId > 0) {
            sql.appendSql(" and publish.province_id = ").appendValue(provinceId);
        }
        
        sql.appendSql(" and publish.start_date <= ").appendValue(nowDate);
        sql.appendSql(" and publish.end_date >= ").appendValue(nowDate);
        sql.appendSql(" order by publish.create_at desc");
        if(limit > 0) {
        	sql.appendSql(" LIMIT ").appendValue(limit);
        }
        
        try {
            List<PromotionPublish> list = geliDao.list(PromotionPublish.class, sql.getSql(), sql.getValues());
            return list;
        } catch (DataAccessException e) {
            log.error("listPromotionPublishByProvinceId throws DataAccessException");
            return null;
        }

    }

    /**
     * @Description: 根据优惠活动主表id查找车友会优惠活动
     * @param:
     * @param promotionId 活动id
     * @return: List<PromotionPublish>
     * @Date 2014-10-16 下午05:13:29
     */
    public List<PromotionPublish> listBypromotionId(long promotionId) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql("select publish_id from ").appendSql(geliOrm.getTableName(PromotionPublish.class)).appendSql(" where 1=1");
        if (promotionId > 0) {
            sql.appendSql(" and promotion_id = ").appendValue(promotionId);
        }
        try {
            List<PromotionPublish> list = geliDao.list(PromotionPublish.class, sql.getSql(), sql.getValues());
            return list;
        } catch (DataAccessException e) {
            log.error("listBypromotionId throws DataAccessException");
            return null;
        }
    }

    /**
     * 转换为优惠活动的Json格式
     *
     * @param promotionPublish
     * @param sourceAgent
     * @return
     */
    public JSONObject setPromotionPublishToJson(PromotionPublish promotionPublish, int sourceAgent) {
        JSONObject jsonObject = new JSONObject();
        Promotion promotion = findPromotion(promotionPublish.getPromotionId());
        jsonObject.put("topicUrl", promotion == null ? "" : promotion.getUrl());
        jsonObject.put("img", promotion == null ? "" : promotion.getLogo());
        jsonObject.put("time", promotionPublish.getCreateAt());
        jsonObject.put("startTime", promotionPublish.getStartDate());
        jsonObject.put("endTime", promotionPublish.getEndDate());
        jsonObject.put("title", promotion == null ? "" : EncodeUtils.encodeForHTML(promotion.getName(), sourceAgent) );
        return jsonObject;
    }

    /**
     * 检查车友会Id不等的情况下，主题省市品牌车系的情况
     *
     * @param p
     * @param club
     * @return
     */
    private boolean checkThemeOrCityOrSerial(PromotionPublish p, Club club) {
        if (p.getThemeId() > 0) {//选了主题
            if (p.getThemeId() != club.getThemeId()) {
                if (!checkCityOrSerial(p, club)) {
                    return false;
                }
            }
        } else {//不选主题 
            if (!checkCityOrSerial(p, club)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 检查主题不等的情况，省市品牌车系的情况
     *
     * @param p
     * @param club
     * @return
     */
    private boolean checkCityOrSerial(PromotionPublish p, Club club) {
        if (p.getProvinceId() == 0 && p.getCityId() == 0) {//不选省市
            if (!checkSerial(p, club)) {
                return false;
            }
        } else if (p.getProvinceId() > 0 && p.getCityId() == 0) {//只选省
            if (p.getProvinceId() != club.getProvinceId()) {
                return false;
            }
            if (!checkSerial(p, club)) {
                return false;
            }
        } else if (p.getProvinceId() > 0 && p.getCityId() > 0) {//选了省市
            if (p.getCityId() != club.getCityId()) {
                return false;
            }
            if (!checkSerial(p, club)) {
                return false;
            }
        } else {//不存在只选了市，不选省的情况
            return false;
        }
        return true;
    }

    /**
     * 检查省市相等的情况下，车系的情况
     *
     * @param p
     * @param club
     * @return
     */
    private boolean checkSerial(PromotionPublish p, Club club) {
        if (p.getBrandId() == 0 && p.getSerialId() == 0) {//不选品牌车系
            return true;//不选就不限制了
        } else if (p.getBrandId() > 0 && p.getSerialId() == 0) {//只选了品牌
            if (p.getBrandId() != club.getBrandId()) {
                return false;
            }
        } else if (p.getBrandId() > 0 && p.getSerialId() > 0) {//选了品牌车系
            if (p.getSerialId() != club.getSeriesId()) {
                return false;
            }
        } else {//没有只选车系不选品牌的情况
            return false;
        }
        return true;
    }

    /**
     * 获取某车友会满足条件的所有优惠活动
     *
     * @param clubId
     * @return
     */
    public List<Promotion> listByClubId(long clubId, int num) {
        Club club = clubService.getClub(clubId);
        String nowDate = DateUtils.format(new Date());
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql("select publish_id from ").appendSql(geliOrm.getTableName(PromotionPublish.class));
        sql.appendSql(" where (club_id = ").appendValue(club.getClubId());
        if (club.getProvinceId() > 0) {
            sql.appendSql(" or province_id = ").appendValue(club.getProvinceId());
        }
        if (club.getCityId() > 0) {
            sql.appendSql(" or city_id = ").appendValue(club.getCityId());
        }
        if (club.getBrandId() > 0) {
            sql.appendSql(" or brand_id = ").appendValue(club.getBrandId());
        }
        if (club.getSeriesId() > 0) {
            sql.appendSql(" or serial_id = ").appendValue(club.getSeriesId());
        }
        if (club.getThemeId() > 0) {
            sql.appendSql(" or theme_id = ").appendValue(club.getThemeId());
        }
        sql.appendSql(" or ( club_id =0 and province_id=0 and city_id=0 and brand_id=0 and serial_id=0 and theme_id=0) ");
        sql.appendSql(" ) and start_date <= ").appendValue(nowDate);
        sql.appendSql(" and end_date >= ").appendValue(nowDate);
        try {
            List<PromotionPublish> list = geliDao.list(PromotionPublish.class, sql.getSql(), sql.getValues());
            List<Long> ids = new ArrayList<Long>();
            for (PromotionPublish p : list) {
                if (p.getProvinceId() != 0 || p.getCityId() != 0 || p.getBrandId() != 0 || p.getSerialId() != 0
                        && p.getThemeId() != 0 || p.getClubId() != 0) {
                    if (p.getClubId() > 0) {
                        if (p.getClubId() != club.getClubId()) {
                            if (!checkThemeOrCityOrSerial(p, club)) {
                                continue;
                            }
                        }
                    } else {
                        if (!checkThemeOrCityOrSerial(p, club)) {
                            continue;
                        }
                    }
                }//筛选条件全为0时，表示发布到全部车友会
                if (!ids.contains(p.getPromotionId())) {
                    ids.add(p.getPromotionId());
                }
            }
            if (ids.isEmpty()) {
                return null;
            }
            List<Promotion> promotionList = geliDao.list(Promotion.class, ids.toArray());
            Collections.sort(promotionList, new Comparator() {
                @Override
                public int compare(Object o1, Object o2) {
                    return ((Promotion) o2).getSortWeight() - ((Promotion) o1).getSortWeight();
                }
            });
            //过滤已删除的优惠活动
            List<Promotion> subList = new ArrayList(num);
            for (Promotion p : promotionList) {
                if (p.getStatus() == Promotion.STATUS_DELETE) {
                    continue;
                }
                if (subList.size() < num) {
                    subList.add(p);
                } else {
                    break;
                }
            }
            return subList;
        } catch (EmptyResultDataAccessException e) {
            log.error("listBypromotionId throws DataAccessException");
            return null;
        }
    }

    /**
     * 获取同城优惠（已根据权重排序）
     *
     * @param provinceId
     * @param cityId
     * @return
     */
    public Pager<Promotion> pagetongChen(long provinceId, long cityId, int pageNo, int pageSize) {
        if (provinceId <= 0) {
            return null;
        }
        boolean flag = isMunicipality(provinceId);
        if (!flag && cityId <= 0) {
            return null;
        }
        String nowDate = DateUtils.format(new Date());
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql("select distinct(promotion.promotion_id) from ").appendSql(geliOrm.getTableName(Promotion.class)).appendSql(" promotion LEFT JOIN ")
                .appendSql(geliOrm.getTableName(PromotionPublish.class)).appendSql(" publish ON promotion.promotion_id = publish.promotion_id ");
        sql.appendSql(" where 1=1 ");
        if (flag) {
            sql.appendSql(" and publish.province_id  = ").appendValue(provinceId);
        } else {
            sql.appendSql(" and publish.city_id = ").appendValue(cityId);
            if (provinceId > 0) {
                sql.appendSql(" and publish.province_id  = ").appendValue(provinceId);
            }
        }
        sql.appendSql(" and promotion.status >=0");
        sql.appendSql(" and publish.start_date <=").appendValue(nowDate).appendSql(" and publish.end_date >=").appendValue(nowDate);
        sql.appendSql(" order by promotion.sort_weight desc");
        try {
            Pager<Promotion> pager = pagerService.pager(Promotion.class, sql, pageNo, pageSize);
            String countSql = sql.getSql().replace(sql.getSql().substring(0, sql.getSql().toLowerCase().indexOf("from")), "select count(distinct(promotion.promotion_id)) ");
            countSql = countSql.replace(countSql.substring(countSql.toLowerCase().indexOf("order by"), countSql.length()), "");
            int count = geliDao.count(countSql, sql.getValues());
            pager.setTotal(count);
            return pager;
        } catch (Exception e) {
            log.error("pagetongChen throws Exception...", e);
            return null;
        }
    }

    /**
     * p判断是否直辖市，特别行政区
     *
     * @param provinceId
     * @return
     */
    public boolean isMunicipality(long provinceId) {
        boolean flag = Promotion.specialProIds.contains(provinceId);
        return flag;
    }

    /**
     * @Description: 获取优惠推送范围
     * @return: String
     */
    public String getPushRange(long promotionId) {
        String returnMessage = "";
        List<PromotionPublish> list = listBypromotionId(promotionId);
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                PromotionPublish promotionPublish = list.get(i);
                if (promotionPublish.getProvinceId() > 0) {
                    returnMessage += promotionPublish.getProvinceName();
                }
                if (promotionPublish.getCityId() > 0) {
                    returnMessage += promotionPublish.getCityName();
                }
                if (promotionPublish.getBrandId() > 0) {
                    returnMessage += promotionPublish.getBrandName();
                }
                if (promotionPublish.getSerialId() > 0) {
                    returnMessage += promotionPublish.getSeriesName();
                }
                long themeId = promotionPublish.getThemeId();
                if (themeId > 0) {
                    Theme theme = geliDao.find(Theme.class, themeId);
                    if (theme != null) {
                        returnMessage += theme.getThemeName();
                    }
                }
                long clubId = promotionPublish.getClubId();
                if (clubId > 0) {
                    try {
                        Club club = geliDao.find(Club.class, clubId);
                        returnMessage += club.getName();
                    } catch (DataAccessException e) {
                    }
                }
                if (i < list.size() - 1) {
                    returnMessage += "，";
                }
            }

            if (returnMessage.equals("")) {
                return "全部车友会";
            }

        } else {
            return "无";
        }
        return returnMessage;
    }
}
